// Copyright (c) Appeon. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.

using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using SnapObjects.Commons;

namespace SnapObjects.Data
{
    public static class DataPackerExtensions
    {
        public static void AddValue<TValue>(
            [NotNull]this IDataPacker dataPacker,
            [NotNull]string key,
            [NotNull]TValue value)
        {
            Check.NotNull(dataPacker, nameof(dataPacker));
            Check.NotNull(key, nameof(key));
            Check.NotNull(value, nameof(value));

            ((DataPacker)dataPacker).AddFormater(key, new NormalPackerFormater<TValue>(value));
        }

        public static IDataIncludeSetter<TModel> AddModel<TModel>(
            [NotNull]this IDataPacker dataPacker,
            [NotNull]string key,
            [NotNull]TModel value) where TModel : class
        {
            Check.NotNull(dataPacker, nameof(dataPacker));
            Check.NotNull(key, nameof(key));
            Check.NotNull(value, nameof(value));

            ((DataPacker)dataPacker).AddFormater(key, new NormalPackerFormater<TModel>(value));

            return new DataIncludeSetter<TModel>(key, value, dataPacker);
        }

        public static IDataIncludeSetter<TModel> AddModels<TModel>(
            [NotNull]this IDataPacker dataPacker,
            [NotNull]string key,
            [NotNull]IEnumerable<TModel> models) where TModel : class
        {
            Check.NotNull(dataPacker, nameof(dataPacker));
            Check.NotNull(key, nameof(key));
            Check.NotNull(models, nameof(models));

            ((DataPacker)dataPacker).AddFormater(key, new NormalPackerFormater<IEnumerable<TModel>>(models));

            return new DataIncludeSetter<TModel>(key, models, dataPacker);
        }

        public static TValue GetValue<TValue>(
            [NotNull]this IDataPacker dataPacker,
            [NotNull]string key)
        {
            Check.NotNull(dataPacker, nameof(dataPacker));
            Check.NotNull(key, nameof(key));

            var parser = DataParserFactory.GetDataPackerParser(dataPacker.DataFormat);

            return parser.Convert<TValue>(dataPacker.GetRaw(key));
        }

        public static IDataIncludeGetter<TModel> GetModel<TModel>(
            [NotNull]this IDataPacker dataPacker,
            [NotNull]string key) where TModel : class
        {
            Check.NotNull(dataPacker, nameof(dataPacker));
            Check.NotNull(key, nameof(key));

            TModel model = null;

            var raw = dataPacker.GetRaw(key);

            if (!String.IsNullOrWhiteSpace(raw))
            {
                var parser = DataParserFactory.GetDataPackerParser(dataPacker.DataFormat);

                model = parser.Convert<TModel>(raw);
            }

            return new DataIncludeGetter<TModel>(key, model ?? default, dataPacker);
        }

        public static IDataIncludeGetter<TModel> GetModels<TModel>(
            [NotNull]this IDataPacker dataPacker,
            [NotNull]string key) where TModel : class
        {
            Check.NotNull(dataPacker, nameof(dataPacker));
            Check.NotNull(key, nameof(key));

            IList<TModel> items = null;

            var raw = dataPacker.GetRaw(key);

            if (!String.IsNullOrWhiteSpace(raw))
            {
                var parser = DataParserFactory.GetDataPackerParser(dataPacker.DataFormat);

                items = parser.Convert<List<TModel>>(raw);
            }

            return new DataIncludeGetter<TModel>(key, items ?? new List<TModel>(), dataPacker);
        }
    }
}
